﻿Imports Aricie.DNN.Modules.LuceneSearch.Business
Imports DotNetNuke.Services.Localization
Imports Aricie.DNN.Services
Imports Lucene.Net.Search
Imports Lucene.Net.Index

Namespace Aricie.DNN.Modules.LuceneSearch.UI.FilteringControls.Basic
    Public Class FieldDropDownList
        Inherits SimpleFilteringControl

        Private _nullLabel As String
        Private _displayEmptyItem As Boolean = True
        Private _defaultItem As String
        Private Shared ReadOnly MultiFieldSeparator As String = "___!MF!___"

        Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
            If Not IsPostBack Then
                BindLayout()
            End If
        End Sub

        Private Sub ddlListField_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles ddlListField.SelectedIndexChanged
            If AutoPostBack Then
                SignalFilterChanged()
            End If
        End Sub

        Public Overrides Property Enabled As Boolean
            Get
                Return ddlListField.Enabled
            End Get
            Set(value As Boolean)
                ddlListField.Enabled = value
            End Set
        End Property

        Public Overridable Property AutoPostBack() As Boolean
            Get
                Return ddlListField.AutoPostBack
            End Get
            Set(ByVal value As Boolean)
                ddlListField.AutoPostBack = value
            End Set
        End Property

        Public Property NullLabel() As String
            Get
                Return _nullLabel
            End Get
            Set(ByVal value As String)
                _nullLabel = value
            End Set
        End Property

        Public Property DisplayEmptyItem() As Boolean
            Get
                Return _displayEmptyItem
            End Get
            Set(ByVal value As Boolean)
                _displayEmptyItem = value
            End Set
        End Property

        Public Property DefaultItem() As String
            Get
                Return _defaultItem
            End Get
            Set(ByVal value As String)
                _defaultItem = value
            End Set
        End Property

        Private Function CheckMatchingQuery(q As Query) As Boolean
            Dim Filter = Filtering.FluentFilterRulesManagerFactory.Init() _
                         .Expects(Of TermQuery)("Une seule valeur présente") _
                         .ExpectsComplex("Plusieurs valeurs possible", AddressOf IsBooleanQueryValid) _
                         .Create()
            Return Filter.Matches(q)
        End Function

        Private Function IsBooleanQueryValid(q As BooleanQuery) As Boolean
            For Each c As BooleanClause In q.GetClauses()
                If Not TypeOf c.Query() Is TermQuery OrElse Not TypeOf c.Query() Is PhraseQuery Then
                    Return False
                End If
                If (TypeOf c.Query() Is TermQuery) Then
                    Dim TQ = DirectCast(c.Query(), TermQuery)
                    If (TQ.Term().Field <> Fields) Then
                        Return False
                    End If
                Else
                    Dim PQ = DirectCast(c.Query(), PhraseQuery)
                    For Each t In PQ.GetTerms()
                        If t.Field <> Fields Then
                            Return False
                        End If
                    Next
                End If
            Next
            Return True
        End Function

        Public Overrides Function ReadFilter(q As Lucene.Net.Search.Query) As Boolean
            If Not CheckMatchingQuery(q) Then
                Return False
            End If

            If TypeOf q Is TermQuery Then
                ddlListField.SelectedValue = BusinessController.GetTermText(DirectCast(q, TermQuery).Term())
            Else
                Dim ValueList As New List(Of String)
                For Each c As BooleanClause In DirectCast(q, BooleanQuery).GetClauses
                    If TypeOf c.Query Is TermQuery Then
                        Dim TQ As TermQuery = DirectCast(c.Query, TermQuery)
                        Dim CurrentTerm As Term = TQ.Term()
                        ValueList.Add(CurrentTerm.Text)
                    End If

                    If TypeOf c.Query Is PhraseQuery Then
                        Dim TQ As PhraseQuery = DirectCast(c.Query, PhraseQuery)
                        For Each currentTerm As Term In TQ.GetTerms
                            ValueList.Add(currentTerm.Text)
                        Next
                    End If
                Next
                ddlListField.SelectedValue = String.Join(MultiFieldSeparator, ValueList.ToArray)
            End If

            Return True
        End Function

        Public Overrides Function SetFilter() As Lucene.Net.Search.Query
            ' on renvoie une clause booléenne qui prend en compte les différentes possibilités de valeur sélectionnée sur le terme
            Dim BQ As New BooleanQuery()
            For Each ValuePart As String In Value.Split(New String() {MultiFieldSeparator}, StringSplitOptions.RemoveEmptyEntries)
                Dim phrase As New PhraseQuery
                phrase.Add(New Term(Fields, ValuePart))
                BQ.Add(phrase, Occur.SHOULD)
            Next
            Return BQ
        End Function

        Public Overrides ReadOnly Property Value As String
            Get
                Return ddlListField.SelectedValue
            End Get
        End Property

        Public Property NbValues As Integer
        Public Property ToUpper As Boolean


        Protected Overridable Sub BindLayout()
            Dim objListTermInfo As List(Of Business.TermInfo) = PortalQueryingDriver.GetCurrent().GetTopTerms(Fields, NbValues)

            If objListTermInfo.Count <> 0 Then

                If Me.DisplayEmptyItem Then
                    If Not String.IsNullOrEmpty(Me.NullLabel) Then
                        ddlListField.Items.Add(New ListItem(Me.NullLabel, String.Empty))
                    Else
                        ddlListField.Items.Add("")
                    End If
                End If

                For Each termInfo As Business.TermInfo In objListTermInfo

                    Dim TextValue As String = termInfo.Text
                    Dim FI As FieldDefinition = FieldFactory.Instance().GetDefinition(Fields)
                    If FI.LocalizeValuedInstance Then
                        ' localisé par instance, on cherche la combinaison dans le fichier de ressources
                        Dim ResultValue As String = Localization.GetString(Fields & "." & TextValue, _
                                NukeHelper.GetModuleSharedResourceFile(Aricie.DNN.Modules.LuceneSearch.Common.Constants.ModuleNameLuceneSearchResults))
                        If (Not String.IsNullOrEmpty(ResultValue)) Then
                            ' si la clé de resource est vide, on garde la version originale, sinon on affiche la resource
                            TextValue = ResultValue
                        End If
                    End If

                    If ToUpper Then
                        TextValue = TextValue.ToUpper
                    End If
                    If (Not String.IsNullOrEmpty(termInfo.Text) AndAlso Not String.IsNullOrEmpty(TextValue)) Then
                        Dim li As New ListItem(TextValue, termInfo.Text)
                        Dim existingLi As ListItem = ddlListField.Items.FindByText(TextValue)
                        If existingLi Is Nothing Then
                            ddlListField.Items.Add(li)
                        Else
                            existingLi.Value = existingLi.Value & MultiFieldSeparator & termInfo.Text
                        End If
                    End If
                Next
                If Not String.IsNullOrEmpty(DefaultItem) Then
                    ddlListField.SelectedValue = DefaultItem
                End If
            Else
                ddlListField.Visible = False
            End If

        End Sub
    End Class
End Namespace